<?php

class DbModel
{
    protected $conn;

    function __construct($type, $host, $db_name, $username, $password, $lang = "utf8")
    {
        try {
            $this->conn = new PDO(
                "$type:host=$host;dbname=$db_name",
                $username,
                $password
            );
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->conn->exec("SET CHARACTER SET " . $lang);
        } catch (Exception $e) {
            die($e);
        }
    }

    function __destruct()
    {
        $this->conn = null;
    }

    private function checkIsDbTable($data)
    {
        if (!is_subclass_of($data, 'DbTable')) {
            error_log('This object is not a instance of DbTable!');
            return false;
        }
        return true;
    }

    public function add($data)
    {
        if ($this->checkIsDbTable($data)) {
            try {
                $this->conn->exec($data->add());
                return true;
            } catch (Exception $e) {
                error_log($e);
                return false;
            }
        }
        return false;
    }

    public function delete($data)
    {
        if ($this->checkIsDbTable($data)) {
            foreach ($data->checkRelationship() as $item) {
                $result = $this->conn->query($item)->fetchAll();
                if (count($result) > 0) {
                    return false;
                }
            }
            return $this->conn->exec($data->delete());
        }
        return false;
    }

    public function edit($data, array $newData)
    {
        $flag = false;
        if ($this->checkIsDbTable($data)) {
            $temp = $data->copy();
            $prepare = $data->edit($newData);
            if ($prepare != null)
                $flag = $this->conn->exec($prepare);
            if (!$flag) {
                $data->changeTo($temp);
            }
        }
        return $flag;
    }

    public function query($obj, $condition)
    {
        if ($this->checkIsDbTable($obj)) {
            $result = $this->conn->query($obj->query($condition))->fetchAll();
            if (count($result) > 0)
                return $obj->loadData($result[0]);
        }
        return false;
    }

    public function list($obj, $page, $pageSize,$condition=null)
    {
        if (isset($obj["class"])) {
                $pre = call_user_func(array($obj["class"], "query"), ["page" => $page, "pageSize" => $pageSize,"condition"=>$condition]);
                debug(explode("limit",$pre));
                $count_sql = "select count(*) from(".explode("limit",$pre)[0].") as _count;";
                $count=$this->conn->query($count_sql)->fetch();

                $result = $this->conn->query($pre)->fetchAll();
                $total=(int)$count[0];
                $list = [];

                foreach ($result as $item) {
                    $c = $obj['class'];
                    $temp = new $c;
                    $flag = call_user_func(array($temp, "loadData"), $item);
                    if ($flag) {
                        debug($item);
                        if (isset($obj['type']) && $obj['type'] == "object"){
                            array_push($list, $temp);
                        }
                        else{
                            array_push($list, json_decode(call_user_func(array($temp, "__toString"))));
                        }

                    }
                }
                return ["list"=>$list,"total"=>$total];

        }
    }
}